iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 16
1
Modern Web

今晚,我想來點Blazor系列 第 16

Day 16:Cascading Paramater

  • 分享至 

  • xImage
  •  

昨天看過Parameter後,今天來看看另外一個元件傳遞資料的方式 — Cascading Parameter。

Cascading Parameter與Parameter的差別在於,Parameter是父元件往下一層的子元件傳遞資料,而Cascading Parameter則是可以往父元件下面一連串的子元件傳遞

元件樹

我們的應用程式就像下圖一樣,是有一連串的元件組合而成的,Parameter的傳遞方式只能往下一層傳遞,以下圖來看,就是Parent傳給C1或C2這2個子元件,那如果要從Parent傳到C3、C4或C5呢? 這時候Cascading Parameter就要上場了。https://ithelp.ithome.com.tw/upload/images/20200930/201300588qFCuj4Sms.png

基本用法

這邊使用上一篇的Todolist範例,我們要在MainLayout設定color屬性,並讓底下的所有元件都能取得color的值。
https://ithelp.ithome.com.tw/upload/images/20200930/20130058MaudjKzvzP.png

首先在MainLayout.razor,我們設定一個color屬性並給預設值red,然後使用CascadingValue將@body包起來,設定Value為@color

<CascadingValue Value="@color">
            @Body
</CascadingValue>

@code{
private string color = "red";
}

在Todo元件中,新增一個[CascadingParamter]屬性接收傳來的值,並繫結到tr的style,注意這邊的型別要與Parent設定的一致。

<tr style="color:@color">
    <td>@ItemName </td>
    <td><button class="btn btn-danger btn-sm" @onclick="Delete">delete</button></td>
</tr>

@code {
    //略...
    [CascadingParameter]
    public string color { get; set; }
}

Todo Item的文字就變紅色囉
https://ithelp.ithome.com.tw/upload/images/20200930/20130058QOScKcAYlr.png

傳遞多個參數

現在我們再多傳一個參數size到Todo元件,在MainLayout再多加一個CascadingValue元件

<CascadingValue Value="@color">
   <CascadingValue Value="@size">
        @Body
   </CascadingValue>
</CascadingValue>

@code{
    private string color = "red";
    private string size = "16px";
}

Todo元件

<tr style="color:@color;font-size:@size;">
    <td>@Item</td>
    <td><button class="btn btn-danger btn-sm" @onclick="Delete">delete</button></td>
</tr>

@code {
    //略...
    [CascadingParameter]
    public string color { get; set; }

    [CascadingParameter]
    public string size { get; set; }
}

https://ithelp.ithome.com.tw/upload/images/20200930/20130058VKuPtRx0do.jpg

另外一種寫法是使用class,參考以下程式碼:

<div class="content px-4">
        <CascadingValue Value="@state">
            @Body
        </CascadingValue>
    </div>

@code{

    State state = new State();

    public class State
    {
        public string color { get; set; } = "red";
        public string size { get; set; } = "20px";
    }
}

建立State類別(名稱可自訂),將剛剛的color和size設為State類別的屬性,並將CascadingValue元件的Value設為State物件

Todo元件

@using static TodoBlazor.Shared.MainLayout

<tr style="color:@state.color;font-size:@state.size">
    <td>@Item</td>
    <td><button class="btn btn-danger btn-sm" @onclick="Delete">delete</button></td>
</tr>

@code{
    [CascadingParameter]
    public State state { get; set; }
}
  • using State類別的命名空間
  • 設定型別為State的Cascading Parameter
  • tr的css style就可以用物件方式使用color和size屬性,賦值給css style

做一點好玩的吧

上面的範例都是直接從MainLayout取值然後顯示,少了一點互動性,現在我們加上幾顆radio button,讓user可以選擇Todo Item文字的顏色。
先在父元件加上顏色的radio button、文字大小的radio button,還有相關的onchage程式碼:

//顏色radio button
<h4 class="font-weight-bold">選擇顏色:</h4>
@foreach (var item in new string[] { "red", "blue", "green" })
{
    <div class="custom-control custom-radio">
        <input type="radio" id="@item" name="colorRadio" class="custom-control-input" value="@item" @onchange="ColorRadioSelection">
        <label class="custom-control-label" for="@item">@item</label>
    </div>
}

<br />

//文字radio buttons
<h4 class="font-weight-bold">選擇文字大小:</h4>
@foreach (var item in new string[] { "16px", "20px", "40px" })
{
    <div class="custom-control custom-radio">
        <input type="radio" id="@item" name="sizeRadio" class="custom-control-input" value="@item" @onchange="SizeRadioSelection">
        <label class="custom-control-label" for="@item">@item</label>
    </div>
}

@code{
    [CascadingParameter]
    public State state { get; set; }   

    void RadioSelection(ChangeEventArgs args)
    {
        state.color = args.Value.ToString();      
    }
    
    void SizeRadioSelection(ChangeEventArgs args)
    {
        state.size = args.Value.ToString();
    }
}
  • Todolist元件一樣宣告一個型別為State的Cascading Parameter
  • RadioSelection方法裡,用ChangeEventArgs取得選取radio button的值,並設定給state屬性

另外我們如果在其他元件宣告state這個cascading parameter的話,在Todolist的變更也會反映到其他元件上,例如現在在counter一樣宣告State屬性,並設定h1 Counter的css:

@page "/counter"
@using static TodoBlazor.Shared.MainLayout

<h1 style="color:@state.color;font-size:@state.size">Counter</h1>

<p>Current count: @currentCount</p>

<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>

@code {

    [CascadingParameter]
    public State state { get; set; }

    private int currentCount = 0;

    private void IncrementCount()
    {
        currentCount++;
    }
}

設定不更新Cascading Parameter Value

從今天這幾個例子可以知道,父元件Cascading Parameter的Value只要一變更,所有底下的子元件都會偵測到變更,並修改子元件中的Cascading Parameter值,因此如果確定父元件的Cascading Parameter不會變更的話,可以設定IsFixed="true",Blazor就不需要耗費資源去更新子元件了。

<CascadingValue Value="@state" IsFixed="true">
       @Body
</CascadingValue>

上一篇
Day 15:元件之間的溝通
下一篇
Day 17:樣板元件(1)
系列文
今晚,我想來點Blazor30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言